<template>
  <div class="control-config-panel">
    <a-tabs v-model:activeKey="activeTab">
      <a-tab-pane key="base" title="基本信息">
        <BaseNodeInfoPanel
          :label="local.label"
          :description="local.description"
          @update:label="(v) => (local.label = v)"
          @update:description="(v) => (local.description = v)"
        />
      </a-tab-pane>

      <a-tab-pane key="control" title="控制属性">
        <div class="control-container">
          <div class="control-header">
            <h4>控制配置</h4>
          </div>

          <div class="control-content">
            <div class="control-mode">
              <a-radio-group v-model="local.controlMode" type="button">
                <a-radio value="all">全部满足</a-radio>
                <a-radio value="partial">部分满足</a-radio>
                <a-radio value="any">任意满足</a-radio>
              </a-radio-group>
            </div>

            <div v-if="local.controlMode === 'partial' || local.controlMode === 'any'" class="partial-select">
              <label>选择需要满足的节点（可多选）</label>
              <a-select
                v-model="local.partialNodeKeys"
                allow-clear
                multiple
                placeholder="请选择需要满足的节点"
                style="width: 100%"
              >
                <a-option
                  v-for="n in availableNodes"
                  :key="nId(n)"
                  :value="nId(n)"
                  :label="nLabel(n)"
                >
                  {{ nLabel(n) }}
                </a-option>
              </a-select>
            </div>
          </div>
        </div>
      </a-tab-pane>

      <a-tab-pane key="outputs" title="自定义出参">
        <BaseOutputsPanel v-model="local.outputs" />
      </a-tab-pane>
    </a-tabs>

    <div class="panel-actions">
      <a-button type="primary" size="small" @click="save">保存</a-button>
      <a-button size="small" @click="$emit('close')">关闭</a-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watch, computed } from 'vue';
import BaseNodeInfoPanel from './base/BaseNodeInfoPanel.vue';
import BaseOutputsPanel from './base/BaseOutputsPanel.vue';

const props = defineProps<{
  node: any;
  // 画布的节点列表（可选）。元素结构建议包含：
  // - id: string
  // - data: { label?: string; nodeKey?: string }
  nodes?: any[];
  // 画布的边列表（用于过滤只允许选择与当前控制节点相连的来源节点）
  edges?: any[];
}>();
const emit = defineEmits(['update', 'close']);

const activeTab = ref('base');

// 画布节点与边
const canvasNodes = computed(() => props.nodes || []);
const canvasEdges = computed(() => props.edges || []);
const nLabel = (n: any) => n?.data?.label ?? n?.label ?? n?.id ?? '未命名节点';
// 统一使用节点 id 作为选值，与 edges 的 source/target 对齐
const nId = (n: any) => n?.id;

// 仅允许选择：所有指向当前控制节点的入边来源节点
const incomingSourceIds = computed<string[]>(() =>
  (canvasEdges.value as any[])
    .filter((e) => e?.target === props.node?.id)
    .map((e) => String(e.source))
);

const availableNodes = computed<any[]>(() =>
  canvasNodes.value.filter((n: any) => incomingSourceIds.value.includes(String(n?.id)))
);

const local = reactive({
  label: props.node?.data?.label || '',
  description: props.node?.data?.description || '',
  controlMode: props.node?.data?.control?.mode || 'all', // all | partial | any
  partialNodeKeys: (props.node?.data?.control?.selectedNodeKeys as string[]) || [],
  outputs: props.node?.data?.outputs ? JSON.parse(JSON.stringify(props.node.data.outputs)) : [],
});

function save() {
  const control: any = { mode: local.controlMode };
  if (local.controlMode !== 'all') {
    // 仅保留合法的入边来源节点
    const keys = local.partialNodeKeys.filter((k) => incomingSourceIds.value.includes(String(k)));
    const labels = keys
      .map((k) => {
        const found = availableNodes.value.find((n) => String(nId(n)) === String(k));
        return found ? nLabel(found) : k;
      })
      .filter(Boolean);
    control.selectedNodeKeys = keys;
    control.selectedNodeLabels = labels;
  } else {
    control.selectedNodeKeys = [];
    control.selectedNodeLabels = [];
  }
  emit('update', props.node.id, {
    label: local.label,
    description: local.description,
    control,
    outputs: local.outputs,
  });
  emit('close');
}

watch(
  () => props.node,
  (n) => {
    local.label = n?.data?.label || '';
    local.description = n?.data?.description || '';
    local.controlMode = n?.data?.control?.mode || 'all';
    // 初始化时也做一次合法性过滤
    const initKeys = ((n?.data?.control?.selectedNodeKeys as string[]) || []).map(String);
    local.partialNodeKeys = initKeys.filter((k) => incomingSourceIds.value.includes(k));
    local.outputs = n?.data?.outputs ? JSON.parse(JSON.stringify(n.data.outputs)) : [];
  },
  { immediate: true }
);
</script>

<style scoped>
.control-config-panel {
  width: 480px;
  background: var(--color-bg-2, #fff);
  box-shadow: -2px 0 16px rgba(0, 0, 0, 0.08);
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 100;
  padding: 24px 20px 16px 20px;
  display: flex;
  flex-direction: column;
  color: var(--color-text-1, #333);
}

.form-group { margin-bottom: 16px; }
.input { width: 100%; padding: 6px 8px; border: 1px solid #e5e6eb; border-radius: 4px; }

.control-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.control-content { display: flex; flex-direction: column; gap: 12px; }

.radio-item { display: inline-flex; align-items: center; margin-right: 16px; }
.radio-item input { margin-right: 6px; }
.radio-label { font-size: 13px; }

.partial-select { display: flex; flex-direction: column; gap: 8px; }
.hint { color: #86909c; font-size: 12px; }

.outputs-list { display: flex; flex-direction: column; gap: 8px; }
.output-item { display: flex; gap: 8px; align-items: center; }
.output-name { flex: 1; }
.output-type { width: 120px; }
.add-btn { margin-top: 8px; }

.panel-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
.save-btn, .close-btn { padding: 6px 12px; border: 1px solid #e5e6eb; border-radius: 4px; background: #fff; cursor: pointer; }
.save-btn { background: #165dff; color: #fff; border-color: #165dff; }
</style>
